package uk.ac.nott.cs.g53dia.bee;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import replay.Player;

import uk.ac.nott.cs.g53dia.Action;
import uk.ac.nott.cs.g53dia.Bee;
import uk.ac.nott.cs.g53dia.Cell;
import uk.ac.nott.cs.g53dia.CommunicateAction;
import uk.ac.nott.cs.g53dia.Environment;
import uk.ac.nott.cs.g53dia.Flower;
import uk.ac.nott.cs.g53dia.HarvestAction;
import uk.ac.nott.cs.g53dia.Point;
import utils.Simulation;

public class ReplayBee extends Bee {
  private Map<Point, Cell> cells;
  private List<Set<Point>> flowersOfType;
  private List<Map<Long, Integer>> samples;
  private Role role;
  private BeeYieldApproximator approximator;
  private Action previousAction;
  private int previousEnergy;


  public ReplayBee(int id) {
    super(id);
    if (id == 0) {
      role = Role.QUEEN;
    } else {
      role = Role.NONQUEEN;
    }
    
    cells = new HashMap<Point, Cell>();
    flowersOfType = new ArrayList<Set<Point>>(Flower.NUM_TYPES);
    for (int i = 0; i < Flower.NUM_TYPES; i++) {
      flowersOfType.add(new HashSet<Point>());
    }
    float[] weights = new float[Flower.NUM_TYPES];
    for (int i = 0; i < Flower.NUM_TYPES; i++) {
      weights[i] = 1f;
    }
    samples = new ArrayList<Map<Long, Integer>>(Flower.NUM_TYPES);
    for (int i = 0; i < Flower.NUM_TYPES; i++) {
      samples.add(new HashMap<Long, Integer>());
    }
    this.approximator = new BeeYieldApproximator(weights, samples);

  }

  @Override
  public void addCells(Map<Point, Cell> cells) {
    this.cells.putAll(cells);
  }

  @Override
  public Bee clone() {
    ReplayBee newBee = new ReplayBee(getId());
    newBee.setPosition(getPosition());
    return newBee;
  }

  @Override
  public void communicate(Bee bee) {
    // pretend doing something    
  }

  @Override
  public Map<Point, Cell> getCells() {
    return cells;
  }

  @Override
  public List<Set<Point>> getFlowersOfType() {
    return flowersOfType;
  }

  @Override
  public Role getRole() {
    return role;
  }

  @Override
  public List<Map<Long, Integer>> getSamples() {
    return samples;
  }

  @Override
  public Action senseAndAct(Cell[][] view, long timestep) {
    final long timeOfDay = (timestep % Environment.DAY_LENGTH);
    if (previousAction instanceof HarvestAction) {
      int type = ((Flower) getCurrentCell(view)).getType();
      approximator.addSample(type, timeOfDay, getEnergy() - previousEnergy);
    }
    previousEnergy = getEnergy();
    previousAction = Simulation.getSimulator().getPlayer().readAction();
    return previousAction;
  }

  @Override
  public int updateFlowersPositions(List<Set<Point>> flowersOfType) {
    int i = 0;
    int sum = CommunicateAction.MIN_PRICE;
    for (Set<Point> flowerType : this.flowersOfType) {
      Set<Point> s = new HashSet<Point>(flowersOfType.get(i));
      s.removeAll(this.flowersOfType.get(i));
      flowerType.addAll(flowersOfType.get(i++));
      sum += s.size();
    }
    return sum > CommunicateAction.MAX_POSITIONS_PRICE ? CommunicateAction.MAX_POSITIONS_PRICE : sum;
  }

  @Override
  public int updateFlowersYields(List<Map<Long, Integer>> samples) {
    return approximator.addSamples(samples);
  }


}
